/*Copyright 2012 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
#limitations under the License.*/

LevelClass = Class.extend({


	/* temporary scroll script for the temporary map 
	make it a loadable JSON or something */
	script: {},
  	/* scrollPoint is an EntityClass instance that indicates where the center of the screen
  	is. This Level Class moves the scrollPoint based on the script. Players should not be 
  	able to move too far from this reference point in x-axis.*/
  	scrollPoint: null,
  	xMaxOffset: null, // the maximum x-distance a player can be from scrollPoint
  	
  	/* actual step in the script being executed */
	scriptStep: null,
	spawnStep: null,
	mapLoaded : null,
	scriptloaded : null,
	music: null,

	// PRE: script is well-formed: has start position, 1 or more steps and 0 or more spawns (can be [])	
	setup: function (mapname) {
		//load the level map and script
		this.mapLoaded = false;
		this.scriptLoaded= false
		xhrGet("./maps/"+mapname+"_map.json", false, function(resp) {
			var map;
			eval('map = ' + resp.responseText);
			gGameEngine.gMap = new TileMapLoaderClass();
    		gGameEngine.gMap.load(map);
    		var assets = new Array();
			for (var i = 0; i < map.tilesets.length; i++) 
			{
				assets.push("img/" + map.tilesets[i].image.replace(/^.*[\\\/]/, ''));
			};
			Logger.log (assets);
			loadAssets(assets, function() {
				gLevel.mapLoaded = true;
			});
			gLevel.mapLoaded = true;
		});
		
		xhrGet("./maps/"+mapname+"_script.json", false, function(resp) {
			eval('gLevel.script = ' + resp.responseText);
			// define and set start position of scrollpoint
			// initialize level with first step of the script
			gLevel.setStats();
			gLevel.scrollPoint = gGameEngine.spawnEntity ("ScrollPoint", gLevel.script.start.x, gLevel.script.start.y, {name: 'scrollpoint'});
			gLevel.scriptStep = {counter: 0, lastDone: false};
			gLevel.spawnStep = {counter: 0, length: gLevel.script.spawns.length, lastDone: (gLevel.script.spawns.length==0)};
			gLevel.setScriptStep();
			gLevel.scrollPoint.physBody.SetActive(true);
			gLevel.scriptLoaded = true;
		});
		this.xMaxOffset = 380; // TODO: define the minimum viewport width and take 45% of that
	},
	
	ready: function () { 
		return (gLevel.mapLoaded && gLevel.scriptLoaded);
	},
	
	
	update: function () {
		if(!IS_SERVER) return; // only the server determines the level flow and spawning of entities??
		
		// check if the level proceeds to next step or is at end of steps
		if ((this.scriptStep.until.timer && this.scriptStep.until.timer<Date.now()) || 
			(this.scriptStep.until.x && this.scrollPoint.pos.x>this.scriptStep.until.x))
		{
			if (this.scriptStep.lastDone) 
			{
				this.end();
				this.script=null;
				return;
			} 
			else 
			{
				this.scriptStep.counter++;
				this.setScriptStep();
			}
		};
		
		// spawn any entities that come in range
		while (!this.spawnStep.lastDone && (this.script.spawns[this.spawnStep.counter].atx < this.scrollPoint.pos.x)) {
				var spawnEnt = this.script.spawns[this.spawnStep.counter];
				Logger.log("DEBUG: spawning "+spawnEnt.type);
				gGameEngine.spawnEntity (spawnEnt.type, spawnEnt.atx+800, spawnEnt.y, spawnEnt.settings); // 1000 = all spawn 1000 in advance
				this.spawnStep.counter++;
				if (this.spawnStep.counter==this.spawnStep.length) this.spawnStep.lastDone = true;
		};
	},

	setStats: function () {
		this.stats={
			enemies: {total:0, destroyed:0}, 
			bosses:{total:0, destroyed:0}, 
			deaths:0, shots:0, hits:0};

		if (this.script.spawns) {
			this.stats.enemies.total = this.script.spawns.length;
			this.stats.bosses.total = this.script.bosses ? this.script.bosses : 0;
		};
	},

	getStats : function () {
		var responseStats = {
			'commanders killed' : this.stats.bosses.total==0 ? 'none' : (this.stats.bosses.destroyed/this.stats.bosses.total),
			'troops killed' :  this.stats.enemies.total==0 ? 'none' : (this.stats.enemies.destroyed/this.stats.enemies.total),
			'team accuray' : this.stats.shots.total==0 ? 'none' : (this.stats.hits/this.stats.shots),
			'team deaths' : this.stats.deaths
		};
		return responseStats;

	},
			
	/* put the data of the step in the script in the this.step object and start timer and 
	music as necessary */	
	setScriptStep: function () {
		if (this.script.steps.length<=this.scriptStep.counter) this.scriptStep.lastDone = true;
		if (!this.script.steps[this.scriptStep.counter]) return;
		//Logger.log("Setting step: "+ this.scriptStep.counter);
		this.scrollPoint.dir = this.script.steps[this.scriptStep.counter].velocity || {x:0,y:0};
		this.scriptStep.until = this.script.steps[this.scriptStep.counter].until || {timer:1};
		this.scriptStep.music = this.script.steps[this.scriptStep.counter].music || null;
		if (this.scriptStep.until.timer) {
			this.scriptStep.until.timer = (this.scriptStep.until.timer * 1000) + Date.now(); //if there is a timer, set it to now + the seconds defined in this.script
		};
		if (this.scriptStep.music) {
			var path ="./sound/"+this.scriptStep.music;
			Logger.log ("Start music: "+this.scriptStep.music);
			gSM.stopAll();
			this.music = gSM.loadAsync(path, function(s)
			{
				gSM.playSound(path,{looping:true,volume:0.3}); 
			});
		};
	},
	
	end: function () {
		Logger.log ("LEVEL ENDED");
		this.scrollPoint.dir = {x:0,y:0};
		//gGameEngine.unspawnEntity (1); // TODO: give the right ID and unspawn all players(?)
		if (IS_CLIENT) {
			show_mission_end(true); // what will the server do?
			gGameEngine.gPlayer0.physBody.SetActive(false);
		};
	}    
  });

var gLevel = new LevelClass();
